﻿#include "OiPCH.hpp"
#include <QTimer>
#include "View/OiPixmap.hpp"
#include "Tools/OiPlyTool.hpp"

namespace Oi { namespace PLScannerCore {

    class PLScannerWorkerImpl;

    namespace Environment
    {
        bool _startTask;
        bool _newParams;
    }

    namespace WorkResult
    {
        Result::Result()
        {
        }

        Result::Result(const Result& p)
        {
            *this = p;
        }

        Result& Result::operator=(const Result& p)
        {
            result = p.result;
            profile = p.profile;
            data = p.data;
            params = p.params;
            return *this;
        }

        void Result::caculateResult(Result & result, bool dir, void* data)
        {
            PlyTool tool;
            tool.calResult(result, dir);

            //PLScannerWorkerImpl* impl = reinterpret_cast<PLScannerWorkerImpl*>(data);
        }

        void Result::saveResultToDataBase(const Result & result)
        {
//             DataRow row;
//             row.datetime = QDateTime::currentDateTime();
//             row.result = result.result;
//             row.formula = result.params.specName;
//             row.insResult = result.data;
//             row.profile = result.profile;
// 
//             if(Database::instance()->insert(row))
//             {
//             }
        }

        void Result::saveResultToFile(const Result & result, const QString path)
        {
            if(QFileInfo::exists(path))
            {
                QFile::remove(path);
            }

            Core::ZipWriter writer(path);

            if(writer.result() != 0)
            {
                return;
            }

//             QByteArray info;
//             QDataStream sInfo(&info, QIODevice::WriteOnly);
//             sInfo << result.result << result.data;

            QByteArray profile;
            QDataStream sProfile(&profile, QIODevice::WriteOnly);
            sProfile << result.profile;

//            writer.addFile("info.dat", info);
            writer.addFile("profile.dat", profile);

            QString tempFilePath;
            QTemporaryDir dir;
            if(dir.isValid())
            {
                tempFilePath = dir.path() + "/" + QUuid::createUuid().toString();
            }
            else
            {
                tempFilePath = Core::OiGetPermanentDir(TempDir) + "/" + QUuid::createUuid().toString();
            }

            if(ProductParams::saveToLocal(result.params, tempFilePath))
            {
                QFile tempFile(tempFilePath);
                if(tempFile.open(QIODevice::ReadOnly))
                {
                    writer.addFile("params.dat", tempFile.readAll());
                }
            }       
        }

        void Result::loadResultFromDataBase(Result & result, const int id)
        {
//             DataRow row;
//             if(Database::instance()->query(row, id))
//             {
//                 result.result = row.result;
//                 ProductParams::loadFromLocal(result.params, row.formula);
//                 result.data = row.insResult;
//                 result.profile = row.profile;
//             }
        }

        void Result::loadResultFromFile(Result & result, const QString path)
        {
            if(!QFileInfo::exists(path))
            {
                return;
            }

            Core::ZipReader reader(path);

            if(reader.result() != 0)
            {
                return;
            }

//             if(reader.hasFile("info.dat"))
//             {
//                 auto idata = reader.fileData("info.dat");
//                 QDataStream stream(&idata, QIODevice::ReadOnly);
// 
//                 if(!stream.atEnd())
//                 {
//                     stream >> result.result >> result.data;
//                 }
//             }

            if(reader.hasFile("profile.dat"))
            {
                auto pdata = reader.fileData("profile.dat");
                QDataStream stream(&pdata, QIODevice::ReadOnly);

                if(!stream.atEnd())
                {
                    stream >> result.profile;
                }
            }

            if (reader.hasFile("params.dat"))
            {
                QString tempFilePath;
                QTemporaryDir dir;
                if(dir.isValid())
                {
                    tempFilePath = dir.path() + "/" + QUuid::createUuid().toString() + ".pmf";
                }
                else
                {
                    tempFilePath = Core::OiGetPermanentDir(TempDir) + "/" + QUuid::createUuid().toString() + ".pmf";
                }

                QFile tempFile(tempFilePath);
                if(tempFile.open(QIODevice::WriteOnly))
                {
                    tempFile.write(reader.fileData("params.dat"));
                    tempFile.close();
                }

                ProductParams::loadFromLocal(result.params, QString(), tempFilePath);
            }
        }
    }

    class WorkLoopModeTaskImpl : public Impl<WorkLoopModeTask>
    {
    public:
        PLScannerWorkerImpl* _impl = nullptr;        
    };
    class WorkFixedModeTaskImpl : public Impl<WorkFixedModeTask>
    {
    public:
        PLScannerWorkerImpl* _impl = nullptr;

    public:
        QMutex _mutex;

        double _wideOffset = 0.0;

    public:
        QList<double> _values;
        double _value;

    public:
        static void valueUpdate(const double&, void*);
    };

    class PLScannerWorkerImpl : public Impl<PLScannerWorker>
    {
    public:
        PLScannerWorkerImpl() 
        {
        }

    public:
        void init();
        void exit();

    public:
        QTimer _timerProduct;
        int _timeCalib;
        int _heartbeat = 0;

    public:
        WorkLoopModeTask* _loopTaskThread;

    public:
        ProductParams _params;

    public:
        WorkResult::Result _result;
        double _fixedValue;

    public:
        QMutex _mutex;

    public:
        QFuture<void> _future;

    public:
        int _workRet;

    public:
        void wideCalib(OiProfile& ps, double start = 0);

        double wideCalib(double pos);
    };

    void WorkFixedModeTaskImpl::valueUpdate(const double& value, void* data)
    {
        WorkFixedModeTaskImpl * p = reinterpret_cast<WorkFixedModeTaskImpl*>(data);
        int acqMethod = PLScanner::instance()->measureAcqPointMethod;
        double stdValue = p->_impl->_params.fixedPoint.y() - p->_wideOffset - PLScanner::instance()->measureOffsetY - PLScanner::instance()->measureOffsetY_S;

        p->_mutex.lock();

        if (acqMethod == 0)
        {
            p->_values.append(value);
            if (p->_values.size() > 10)
            {
                p->_values.pop_front();
                p->_value = PLScannerUtil::medianV(p->_values);
            }
        }
        else if (acqMethod == 1)
        {
            p->_values.append(value - stdValue);
            if (p->_values.size() > 10)
            {
                p->_values.pop_front();
                p->_value = *(std::min_element(p->_values.begin(), p->_values.end(), [](const double& v1, const double& v2) {return fabs(v1) < fabs(v2); })) + stdValue;
            }
        }
        p->_mutex.unlock();
    }

    void PLScannerWorkerImpl::wideCalib(OiProfile& ps, double start)
    {
        if (!PLScanner::instance()->wideCalibEnable)
        {
            return;
        }
        auto wcp = PLScanner::instance()->wideCalib_P;

        int i = 0, j = 0;
        for (; i < ps.size(); i++)
        {
            while (j < wcp.size())
            {
                if (ps[i].y() > 20 || ps[i].y() < 0.02)
                {
                    if (i < ps.size() - 1 && i > 0)
                    {
                        if (ps[i + 1].y() > 0.01 && ps[i + 1].y() < 10)
                        {
                            ps[i].setY(ps[i - 1].y());
                        }
                        else if (i + 2 < ps.size() - 1 && ps[i + 2].y() > 0.01 && ps[i + 2].y() < 10)
                        {
                            ps[i].setY(ps[i - 1].y());
                        }
                    }
                }
                if (fabs(ps[i].x() + start - wcp[j].x()) < 0.01)
                {
                    ps[i].setY(ps[i].y() + wcp[j].y());
                    j++;
                    break;
                }
                else if (wcp[j].x() < ps[i].x() + start)
                {
                    j++;
                }
                else
                {
                    break;
                }
            }
        }
        //for (double y = ps[i - 1].y(); y > 0; y -= 0.1)
        //{
        //    ps.append(QPointF(ps[0].x(), y));
        //}

        //for (double row = ps[i - 1].x(); row > ps[0].x(); row -= 0.1)
        //{
        //    ps.append(QPointF(row, 0.1));
        //}
        //for (double y = 0; y < ps[0].y(); y += 0.1)
        //{
        //    ps.append(QPointF(ps[0].x(), y));
        //}
        //double x = ps[i - 1].x();
        //double y = ps[i - 1].y();
        //ps.append(QPointF(x + 0.4, 0.1));
        //ps.append(QPointF(x + 0.5, 0.1));
        //x = ps[0].x();
        //y = ps[0].y();
        //ps.prepend(QPointF(x - 0.2, 0.1));
        //ps.prepend(QPointF(x - 0.1, 0.1));

        if (!PLScanner::instance()->saveCorrectedData)
        {
            return;
        }

        QString fileName = PLScanner::instance()->correctedDataDir + "/" + QDateTime::currentDateTime().toString("yyyyMMddhhmmss") + ".csv";

        PLScanner::instance()->saveCSV(fileName, ps);
    }

    double PLScannerWorkerImpl::wideCalib(double pos)
    {
        //         auto wideCalib_A = Core::OiSettings()->value("Calib/WideCalib-A", 0.0).toDouble();
        //         auto wideCalib_B = Core::OiSettings()->value("Calib/WideCalib-B", 0.0).toDouble();
        // 
        //         return  wideCalib_A * pos + wideCalib_B;

        if (!PLScanner::instance()->wideCalibEnable)
        {
            return 0.0;
        }

        auto wcp = PLScanner::instance()->wideCalib_P;

        for (int j = 0; j < wcp.size(); j++)
        {
            if (fabs(pos - wcp[j].x()) < 0.01)
            {
                return wcp[j].y();
            }
        }

        return 0.0;
    }

    WorkLoopModeTask::WorkLoopModeTask(void* impl,  QObject* parent /*= nullptr*/)
        : QThread(parent)
    {
        OI_I(WorkLoopModeTask);

        d->_impl = reinterpret_cast<PLScannerWorkerImpl*>(impl);
    }

    void WorkLoopModeTask::run()
    {
        OI_F(WorkLoopModeTask);

        Motor::instance()->loopMode();

        bool startFlag = true;

        double start = 0.0, end = 0.0;

        int emptyCounter = 0;

        int timeout = PLScanner::instance()->captureTimeout * 1000;
        double sideLen = PLScanner::instance()->sideLen;

        while (Environment::_startTask)
        {
            emit enterRound();

            OiProfile profile;

            bool dir = true;

            if (Motor::instance()->isAlarm())
            {
                OiShowMessage(tr("设备报警"));
                d->_impl->_workRet = 10;

                return;
            }


            if (!PLScanner::instance()->simulation)
            {
                if (Environment::_newParams || startFlag)
                {
                    startFlag = true;
                    Environment::_newParams = false;

                    SensorAcquire::OiAcquire()->abort();

                    if (Motor::instance()->isHome())
                    {
                        Motor::instance()->locateMode();

                        Motor::instance()->locatedRun(0.0);

                        OiShowMessage(tr("正在等待轴运动至0点"));

                        QThread::msleep(1000);

                        int timerCounter = 0;

                        while (!Motor::instance()->locatedModeReady())
                        {
                            if (!Environment::_startTask)
                            {
                                return;
                            }

                            if (timerCounter > 300)
                            {
                                OiShowMessage(tr("等待轴运动过程超时"));
                                d->_impl->_workRet = 11;

                                return;
                            }

                            timerCounter++;

                            QThread::msleep(100);
                        }
                    }
                    else
                    {
                        Motor::instance()->home();

                        OiShowMessage(tr("正在等待轴回零"));

                        Sleep(1000);

                        int timerCounter = 0;

                        while (!Motor::instance()->isReady())
                        {
                            if (!Environment::_startTask)
                            {
                                return;
                            }

                            if (timerCounter > 300)
                            {
                                OiShowMessage(tr("等待轴回零超时"));
                                d->_impl->_workRet = 12;

                                return;
                            }

                            timerCounter++;

                            QThread::msleep(100);
                        }
                    }

                     Sleep(1000);
 
                     Motor::instance()->loopMode();
                }

                if (startFlag)
                {
                    if (!SensorAcquire::OiAcquire()->acquire(nullptr, nullptr, profile, dir, PLScanner::instance()->acquireVel, 0.0, 0.0, true, timeout))
                    {
                        d->_impl->_workRet = 2;
                        return;
                    }

                    int pSize = profile.size();

                    if (pSize >= 7000)
                    {
                        PLScannerUtil::filter(profile, PLScanner::instance()->sideCorrect, 0.5, PLScanner::instance()->filter, PLScanner::instance()->filterLen);

                        if (profile.size() <= 20)
                        {
                            d->_impl->_workRet = 3;
                            return;
                        }
<<<<<<< Updated upstream

=======
>>>>>>> Stashed changes
                        d->_impl->wideCalib(profile);

                        if (PLScanner::instance()->acquireDir)
                        {
                            start = profile.front().x() - sideLen;
                            if (start < 0)
                            {
                                start = 0;
                            }

                            end = profile.last().x() + sideLen;
                            if (end >= PLScanner::instance()->resolution * (pSize - 10))
                            {
                                end = PLScanner::instance()->resolution * (pSize - 10);
                            }
                        }
                        else
                        {
                            start = (PLScanner::instance()->resolution * (pSize - 1) - profile.last().x()) - sideLen;
                            if (start < 0)
                            {
                                start = 0;
                            }
                            end = (PLScanner::instance()->resolution * (pSize - 1) - profile.front().x()) + sideLen;
                            if (end >= PLScanner::instance()->resolution * (pSize - 10))
                            {
                                end = PLScanner::instance()->resolution * (pSize - 10);
                            }
                        }

                        startFlag = false;

                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    if (PLScanner::instance()->autoCalib)
                    {
                        auto dt = QDateTime::currentDateTime().toTime_t();
                        if (dt - d->_impl->_timeCalib > PLScanner::instance()->calibInterval * 3600)
                        {
                            d->_impl->_timeCalib = dt;

                             auto actualValue = Core::OiSettings()->value("Calib/ActuralValue", 0.0).toDouble();
//                             auto wideCalib_A = Core::OiSettings()->value("Calib/WideCalib-A", 0.0).toDouble();
//                             auto wideCalib_B = Core::OiSettings()->value("Calib/WideCalib-B", 0.0).toDouble();

//                            auto wideOffset = wideCalib_A * PLScanner::instance()->calibPos + wideCalib_B;

                            double wideOffset = 0.0;
                            OiWarning() << "单点标定位，位置补偿值：" << wideOffset;

                            double temperature1 = 0.0, temperature2 = 0.0;
                            SensorAcquire::OiAcquire()->readTemperature(temperature1, temperature2);
                            
                            QList<double> measureValue;
                            while (measureValue.size() < 10)
                            {
                                if (!Environment::_startTask)
                                {
                                    return;
                                }
                                double retValue = 0.0;
                                if (SensorAcquire::OiAcquire()->acquire(0, 0, retValue, PLScanner::instance()->calibPos, true, 100, 10000))
                                {
                                    measureValue.append(retValue + wideOffset);
                                }
                                else
                                {
                                    measureValue.append(0.0);
                                }
                            }

                            double mvalue = PLScannerUtil::medianV(measureValue);

                            if (mvalue > 0.0 && actualValue > 0.0 && fabs(mvalue - actualValue) < 0.5)
                            {
                                PLScannerError::instance()->clearError(PLScannerError::ERR_CALIB_INFO);

                                PLScanner::instance()->measureOffsetY = actualValue - mvalue;

                                PLScanner::instance()->saveCalibRecord(temperature1, temperature2, mvalue);

                                OiShowMessage(tr("标定成功"));
                            }
                            else
                            {
                                PLScannerError::instance()->reportError(PLScannerError::ERR_CALIB_INFO);
                            }

                            Motor::instance()->locatedRun(start);

                            QThread::msleep(1000);

                            OiShowMessage(tr("正在等待轴运动至起始点"));

                            int timerCounter = 0;

                            while (!Motor::instance()->locatedModeReady())
                            {
                                if (!Environment::_startTask)
                                {
                                    return;
                                }

                                if (timerCounter > 100)
                                {
                                    OiShowMessage(tr("等待轴运动过程超时"));
                                    d->_impl->_workRet = 4;

                                    return;
                                }

                                timerCounter++;

                                QThread::msleep(100);
                            }

                            Motor::instance()->loopMode();
                            QThread::msleep(100);
                        }
                    }
                    if (!SensorAcquire::OiAcquire()->acquire(nullptr, nullptr, profile, dir, PLScanner::instance()->acquireVel, start, end, true, timeout))
                    {
                        d->_impl->_workRet = 5;
                        return;
                    }

                    PLScannerUtil::filter(profile, PLScanner::instance()->sideCorrect, 0.5, PLScanner::instance()->filter, PLScanner::instance()->filterLen);

                    d->_impl->wideCalib(profile, start);

                    if (profile.size() < 20)
                    {
                        emptyCounter++;
                        if (emptyCounter == 2)
                        {
                            d->_impl->_workRet = 6;
                            return;
                        }
                    }
                    else
                    {
                        emptyCounter = 0;
                    }
                }
            }
            else
            {
                Sleep(2000);

                auto mprofile = d->_impl->_params.profiles[0];
                std::sort(mprofile.begin(), mprofile.end(), [](QPointF p1, QPointF p2) { return p1.x() < p2.x(); });
                mprofile.removeFirst();
                mprofile.removeLast();

                qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));

                double from = mprofile.front().x();
                double end = mprofile.last().x();

                int closeIndex = 0;

                for (int i = from; i < end; i++)
                {

                    while (mprofile[closeIndex].x() > i)
                    {
                        closeIndex--;

                        if (closeIndex <= 0)
                        {
                            closeIndex = 0;
                            break;
                        }
                    }

                    while (mprofile[closeIndex + 1].x() < i)
                    {
                        closeIndex++;

                        if (closeIndex >= mprofile.size() - 2)
                        {
                            closeIndex = mprofile.size() - 2;
                            break;
                        }
                    }

                    Geom::Line2d line(Geom::Point2d(mprofile[closeIndex].x(), mprofile[closeIndex].y()), Geom::Point2d(mprofile[closeIndex + 1].x(), mprofile[closeIndex + 1].y()));

                    double y = line.y_at_x(i);

                    profile.append(QPointF(i, y));
                }

                profile.append(profile.last() + QPointF(1.0, 0.0));
                profile.append(profile.last() + QPointF(1.0, 0.0));
                profile.append(profile.last() + QPointF(1.0, 0.0));
                profile.append(profile.last() + QPointF(1.0, 0.0));
                profile.append(profile.last() + QPointF(1.0, 0.0));
                profile.append(profile.last() + QPointF(1.0, 0.0));


                for (int i = 0; i < profile.size(); i++)
                {
                    profile[i] += QPointF(  300.0, 0.0001 * (qrand() % 1000) - 0.05 );
                }

                PLScannerUtil::filter(profile, PLScanner::instance()->sideCorrect, 0.5, PLScanner::instance()->filter, PLScanner::instance()->filterLen);
            }

            WorkResult::Result mResult;
            mResult.profile = profile;

            d->_impl->_mutex.lock();
            mResult.params = d->_impl->_params;
            d->_impl->_mutex.unlock();

//             if (d->_impl->_future.isRunning())
//             {
//                 PLScannerError::instance()->reportError(PLScannerError::ERR_CACULATE_RESULT_OVERFLOW);
//             }
//             else
//             {
//                 PLScannerError::instance()->clearError(PLScannerError::ERR_CACULATE_RESULT_OVERFLOW);
// 
//                 d->_impl->_future = QtConcurrent::run(WorkResult::Result::caculateResult, mResult, d->_impl);
//             }

            WorkResult::Result::caculateResult(mResult, dir ,NULL);
           
            d->_impl->_mutex.lock();
            d->_impl->_result = mResult;
            d->_impl->_mutex.unlock();

            auto outputSystem = Core::OiSettings()->value("System/OutputSystem").toString();
            if (!outputSystem.isEmpty())
            {
                //             PLScannerOutput output(result);
                //             SliceBalanceOutput::saveToSys(output, outputSystem);
            }

            emit leaveRound();
        }
    }

    WorkFixedModeTask::WorkFixedModeTask(void* impl, QObject* parent /*= nullptr*/)
    {
        OI_I(WorkFixedModeTask);

        d->_impl = reinterpret_cast<PLScannerWorkerImpl*>(impl);
    }

    void WorkFixedModeTask::run()
    {
        OI_F(WorkFixedModeTask);

        Motor::instance()->loopMode();

        bool startFlag = true;

        double start = 0.0, end = 0.0;

        int timeout = PLScanner::instance()->captureTimeout * 1000;

        d->_values.clear();

        while (Environment::_startTask)
        {
            emit enterRound();
            double value = 0.0;
            QPointF pos;

            d->_impl->_mutex.lock();
            pos = d->_impl->_params.fixedPoint;
            d->_impl->_mutex.unlock();

            bool dir = true;

            if (!PLScanner::instance()->simulation)
            {
                if (Environment::_newParams || startFlag)
                {
                    startFlag = true;
                    Environment::_newParams = false;

                    SensorAcquire::OiAcquire()->abort();

                    if (Motor::instance()->isHome())
                    {
                        Motor::instance()->locateMode();

                        Motor::instance()->locatedRun(0.0);

                        OiShowMessage(tr("正在等待轴运动至0点"));

                        QThread::msleep(1000);

                        int timerCounter = 0;

                        while (!Motor::instance()->locatedModeReady())
                        {
                            if (!Environment::_startTask)
                            {
                                return;
                            }

                            if (timerCounter > 300)
                            {
                                OiShowMessage(tr("等待轴运动过程超时"));
                                d->_impl->_workRet = 11;

                                return;
                            }

                            timerCounter++;

                            QThread::msleep(100);
                        }
                    }
                    else
                    {
                        Motor::instance()->home();

                        OiShowMessage(tr("正在等待轴回零"));

                        Sleep(1000);

                        int timerCounter = 0;

                        while (!Motor::instance()->isReady())
                        {
                            if (!Environment::_startTask)
                            {
                                return;
                            }

                            if (timerCounter > 300)
                            {
                                OiShowMessage(tr("等待轴回零超时"));
                                d->_impl->_workRet = 12;

                                return;
                            }

                            timerCounter++;

                            QThread::msleep(100);
                        }
                    }

                    Sleep(1000);

                    Motor::instance()->loopMode();
                }

                if (startFlag)
                {
                    Motor::instance()->loopMode();

                    OiProfile profile;

                    if (!SensorAcquire::OiAcquire()->acquire(nullptr, nullptr, profile, dir, PLScanner::instance()->acquireVel, 0.0, 0.0, true, timeout))
                    {
                        d->_impl->_workRet = 2;
                        return;
                    }

                    int pSize = profile.size();

                    if (pSize >= 7000)
                    {
                        PLScannerUtil::filter(profile, PLScanner::instance()->sideCorrect, 0.5, PLScanner::instance()->filter, PLScanner::instance()->filterLen);

                        if (profile.size() <= 20)
                        {
                            d->_impl->_workRet = 3;
                            return;
                        }

                        if (PLScanner::instance()->acquireDir)
                        {
                            start = profile.front().x();
                           
                            end = profile.last().x();
                           
                        }
                        else
                        {
                            start = (PLScanner::instance()->resolution * (pSize - 1) - profile.last().x());
                           
                            end = (PLScanner::instance()->resolution * (pSize - 1) - profile.front().x());
                        }

                        startFlag = false;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    if (PLScanner::instance()->autoCalib)
                    {
                        auto dt = QDateTime::currentDateTime().toTime_t();
                        if (dt - d->_impl->_timeCalib > PLScanner::instance()->calibInterval * 3600)
                        {
                            SensorAcquire::OiAcquire()->abort();

                            d->_impl->_timeCalib = dt;

                            double temperature1 = 0.0, temperature2 = 0.0;
                            SensorAcquire::OiAcquire()->readTemperature(temperature1, temperature2);

                            auto actualValue = Core::OiSettings()->value("Calib/ActuralValue", 0.0).toDouble();

                            QList<double> measureValue;
                            while (measureValue.size() < 10)
                            {
                                if (!Environment::_startTask)
                                {
                                    return;
                                }
                                double retValue = 0.0;
                                if (SensorAcquire::OiAcquire()->acquire(0, 0, retValue, PLScanner::instance()->calibPos, true, 100, 10000))
                                {
                                    measureValue.append(retValue);
                                }
                                else
                                {
                                    measureValue.append(0.0);
                                }
                            }

                            double mvalue = PLScannerUtil::medianV(measureValue);

                            if (mvalue > 0.0 && actualValue > 0.0 && fabs(mvalue - actualValue) < 0.5)
                            {
                                PLScannerError::instance()->clearError(PLScannerError::ERR_CALIB_INFO);

                                PLScanner::instance()->measureOffsetY = actualValue - mvalue;

                                PLScanner::instance()->saveCalibRecord(temperature1, temperature2, mvalue);

                                OiShowMessage(tr("标定成功"));
                            }
                            else
                            {
                                PLScannerError::instance()->reportError(PLScannerError::ERR_CALIB_INFO);
                            }
                        }
                    }

                    double retValue;
                    double axisPos = (start + end) / 2;
                    if (PLScanner::instance()->acquireDir)
                    {
                        axisPos += pos.x();
                    }
                    else
                    {
                        axisPos -= pos.x();
                    }

                    d->_wideOffset = d->_impl->wideCalib(axisPos);

                    OiWarning() << "Pos:" << axisPos << "Offset:" << d->_wideOffset;

                    SensorAcquire::OiAcquire()->acquire(WorkFixedModeTaskImpl::valueUpdate, d, retValue, axisPos, false, 100);
                    auto modifyType = Core::OiSettings()->value("Calib/ModifyType", 0).toInt();
                    if (modifyType == 1)
                    {
                        auto DatumTemperatureUpSensor = Core::OiSettings()->value("Calib/DatumTemperatureUpSensor", 0.0).toDouble();
                        auto DatumTemperatureDownSensor = Core::OiSettings()->value("Calib/DatumTemperatureDownSensor", 0.0).toDouble();
                        auto deltaUpSensorValue = Core::OiSettings()->value("Calib/deltaUpSensorValue", 0.0).toDouble();
                        auto deltaDownSensorValue = Core::OiSettings()->value("Calib/deltaDownSensorValue", 0.0).toDouble();
                        double temperature1 = 0.0, temperature2 = 0.0;
                        SensorAcquire::OiAcquire()->readTemperature(temperature1, temperature2);
                        d->_mutex.lock();
                        if (d->_value > 0.05)
                        {
                            value = d->_value - ((temperature1- DatumTemperatureUpSensor)*DatumTemperatureUpSensor + (temperature2 - DatumTemperatureDownSensor)*deltaDownSensorValue);
                        }
                        else
                        {
                            value = 0.0;
                        }
                        d->_mutex.unlock();
                    }
                    else
                    {
                        d->_mutex.lock();
                        if (d->_value > 0.05)
                        {
                            value = (d->_value + d->_wideOffset + PLScanner::instance()->measureOffsetY + PLScanner::instance()->measureOffsetY_S);
                            OiWarning() << "d->_value:" << d->_value << "Offset:" << d->_wideOffset << " measureOffsetY" << PLScanner::instance()->measureOffsetY << "measureOffsetY_S" << PLScanner::instance()->measureOffsetY_S;
                        }
                        else
                        {
                            value = 0.0;
                        }
                        d->_mutex.unlock();
                    }
                   
                    QThread::msleep(PLScanner::instance()->pointMeasureInterval * 1000);
                }
            }
            else
            {

                qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));

                value = pos.y() + 0.0001 * (qrand() % 1000) - 0.05;

                QThread::msleep(PLScanner::instance()->pointMeasureInterval * 1000);
            }

            d->_impl->_mutex.lock();
            d->_impl->_fixedValue = value;
            d->_impl->_mutex.unlock();

            auto outputSystem = Core::OiSettings()->value("System/OutputSystem").toString();
            if (!outputSystem.isEmpty())
            {
                //             PLScannerOutput output(result);
                //             SliceBalanceOutput::saveToSys(output, outputSystem);
            }

            emit leaveRound();
        }
    }

    void PLScannerWorkerImpl::init()
    {
        OI_Q(PLScannerWorker);

        Environment::_startTask = false;
        Environment::_newParams = false;

        _loopTaskThread = new WorkLoopModeTask(this, q);

        q->connect(&_timerProduct, &QTimer::timeout, q, &PLScannerWorker::product);

        q->connect(_loopTaskThread, &QThread::finished, q, &PLScannerWorker::onLeaveTask);

        q->connect(_loopTaskThread, &QThread::started, q, &PLScannerWorker::enterTask);
        q->connect(_loopTaskThread, &QThread::finished, q, &PLScannerWorker::leaveTask);
        q->connect(_loopTaskThread, &WorkLoopModeTask::enterRound, q, &PLScannerWorker::enterRound);
        q->connect(_loopTaskThread, &WorkLoopModeTask::leaveRound, q, &PLScannerWorker::leaveRound);
        _timeCalib =0;
        _workRet = 0;
        _timerProduct.start(1000);
    }

    void PLScannerWorkerImpl::exit()
    {
        _timerProduct.stop();

        Environment::_startTask = false;

        _loopTaskThread->wait();
    }

    PLScannerWorker::PLScannerWorker(QWidget* parent) : QObject(parent)
    {
        OI_I(PLScannerWorker)->init();
    }

    PLScannerWorker::~PLScannerWorker()
    {
        OI_E(PLScannerWorker)->exit();
    }

    void PLScannerWorker::setParams(const ProductParams& params)
    {
        OI_F(PLScannerWorker);
        QMutexLocker locker(&d->_mutex);

        if (d->_params != params)
        {
            d->_params = params;
            Environment::_newParams = true;
        }
    }

    int PLScannerWorker::isRunning() const
    {
        OI_C(PLScannerWorker);
        if (d->_loopTaskThread->isRunning())
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }

    WorkResult::Result PLScannerWorker::result()
    {
        OI_F(PLScannerWorker);

        QMutexLocker locker(&d->_mutex);
        return d->_result;
    }

    double PLScannerWorker::value()
    {
        OI_F(PLScannerWorker);

        QMutexLocker locker(&d->_mutex);
        return d->_fixedValue;
    }

    void PLScannerWorker::start(int mode)
    {
        OI_F(PLScannerWorker);

        Environment::_startTask = true;

        if (mode == 0)
        {
            d->_loopTaskThread->start();
        }
        
    }

    void PLScannerWorker::stop()
    {
        OI_F(PLScannerWorker);

        d->_workRet = 1;

        Environment::_startTask = false;

        d->_loopTaskThread->wait();
    }

    void PLScannerWorker::onLeaveTask()
    {
        OI_F(PLScannerWorker);

        OiWarning() << "Stop Working, ret = " << d->_workRet;
        Motor::instance()->locateMode();
        Motor::instance()->locatedRun(0.0);

        Motor::instance()->setResult(10000);

        Environment::_startTask = false;
    }

    void PLScannerWorker::product()
    {
        OI_F(PLScannerWorker);

        auto outputSystem = Core::OiSettings()->value("System/OutputSystem").toString();
        if (!outputSystem.isEmpty())
        {
            if (PLScannerOutput::heartbeat(d->_heartbeat, outputSystem))
            {

            }

            if (d->_heartbeat == 0)
            {
                d->_heartbeat = 1;
            }
            else
            {
                d->_heartbeat = 0;
            }
        }

        if (PLScanner::instance()->paramMode == 0)
        {
            return;
        }

        auto productSystem = Core::OiSettings()->value("System/ProductSystem").toString();
        if (productSystem.isEmpty())
        {
            return;
        }

        if (PLScanner::instance()->paramMode == 1)
        {
            ProductParams product;

            if (ProductParams::loadFromSys(product, productSystem))
            {

                //QMutexLocker locker(&d->_mutex);

                if (d->_params != product)
                {
                    ProductParams::saveToLocal(product);
                    ProductParams::setNext(product.specName);
                    ProductParams::updateParams();

                }
            }
        }
        else if (PLScanner::instance()->paramMode == 2)
        {
            QString specName;

            if (ProductParams::loadNameFromSys(specName, productSystem))
            {
                if (Motor::instance()->switchEnable())
                {
                    //QMutexLocker locker(&d->_mutex);

                    if (d->_params.specName != specName && ProductParams::next() != specName)
                    {
                           OiWarning() << "Read New Spec = " << specName;
//                         ProductParams product;
// 
//                         if (ProductParams::loadFromLocal(product, specName))
//                         {
                            ProductParams::setNext(specName);
                            ProductParams::updateParams();
//                         }
//                         else
//                         {
//                             ProductParams::setNext(product.specName);
//                             ProductParams::updateParams();
//                         }
                        
                    }
                }
            }
           
        }
    }

    void PLScannerWorker::save(const QString& path)
    {
        OI_F(PLScannerWorker);

        d->_mutex.lock();
        WorkResult::Result::saveResultToFile(d->_result, path);
        d->_mutex.unlock();
    }


    void PLScannerWorker::open(const QString& file)
    {
        OI_F(PLScannerWorker);

        OiProfile profile;

        if (!SensorAcquire::OiAcquire()->acquire(file, profile))
        {
            return;
        }

        PLScannerUtil::filter(profile, PLScanner::instance()->sideCorrect, 0.5, PLScanner::instance()->filter, PLScanner::instance()->filterLen);

        if (profile.size() < 20)
        {
            OiAlerter() << tr("轮廓数不足");
            return;
        }

        d->wideCalib(profile);

        WorkResult::Result mResult;
        mResult.profile = profile;
        mResult.params = d->_params;

        WorkResult::Result::caculateResult(mResult, true, NULL);

        d->_mutex.lock();
        d->_result = mResult;
        d->_mutex.unlock();

        emit leaveRound();
    }

   

} }
